#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/wait.h>
#include <errno.h>
#include <string.h>

// 阶乘1,  最大递归调用的深度限制：997 左右
long jc(long n){
   if(n == 1) return 1;

   return n*jc(n-1);
}

// 优化阶乘的写法
long jc2(long num, long ret){
   if(num == 1) return ret;
   
   return jc2(num-1, ret*num);
}

// ./demo2 10
int main(int argc,const char *argv[]){
        if(argc != 2)  return -1;

	long num = 0;
	// 从命令行中读取一个long类型的数值atol(), sscanf()
	// num = atol(argv[1]);
        sscanf(argv[1], "%ld", &num);

	// 1. 创建子进程执行阶乘任务
        pid_t pid = fork();
	if(pid < 0 ){
	   printf("fork error: %s\n", strerror(errno) );
	   _exit(EXIT_FAILURE);
	}

	if(pid == 0){
	    // 子进程执行的程序
	    pid_t local_pid = getpid(); // 子进程号
	    pid_t ppid = getppid(); // 父进程号
	    printf("---sub program(pid: %d, ppid: %d) start--\n", local_pid, ppid);
            sleep(20); // 模拟处理中...
	    long ret = jc2(num, 1);
	    printf("%ld! = %ld\n",num, ret);
	    printf("---sub program(pid: %d, ppid: %d) end---\n", local_pid, ppid);
	    
	    _exit(EXIT_SUCCESS); // 退出子进程，父进程准备回收资源
	}

	// 父进程的处理
	printf("当前进程(%d) 的 %d 子进程正在处理中,请稍后!\n",getpid(), pid);

	// 等待子进程结束
        pid_t p = wait(NULL); // 系统则回收p 的进程的pcb资源 

	printf("wait process id is %d over!\n", p);

	return 0;
}
